
#include "member_BCube.h"

using namespace BWE;

member_BCube::member_BCube(BCube* cube)
{
	boss = cube;
	length = 1.0f;
	width = 1.0f;
	height = 1.0f;
	lengthSegments = 1;
	widthSegments = 1;
	heightSegments = 1;
	rebuild();
}
member_BCube::~member_BCube()
{

}

void member_BCube::rebuild()
{
	int columnCount = (lengthSegments + widthSegments) * 2;
	int flankNumVerts = columnCount * (heightSegments + 1);
	int bottomNumVerts = (widthSegments - 1) * (lengthSegments - 1);
	int topNumVerts = bottomNumVerts;
	int totalNumVerts = flankNumVerts + bottomNumVerts + topNumVerts;

	BVectorArray* vertices = boss->vertices();
	BVectorArray* normals = boss->normals();
	if (!vertices || vertices->size() != totalNumVerts)
	{
		vertices = new BVectorArray(totalNumVerts);
		normals = new BVectorArray(totalNumVerts);
		boss->setVertices(vertices);
		boss->setNormals(normals);
	}
	boss->clearElements();

	BReal hh = height / 2;
	BVector min(-length * 0.5f, -width * 0.5f, -height * 0.5f);
	BVector max(length * 0.5f, width * 0.5f, height * 0.5f);
	BReal dx = length / lengthSegments;
	BReal dy = width / widthSegments;
	BReal dz = height / heightSegments;

	{// flank vertex.
		int count = 0;
		for (int i = 0; i < lengthSegments; i++)
		{
			BReal x = min.x() + dx * i;
			BReal y = min.y();
			(*vertices)[count++] = BVector(x, y, -hh);
		}
		for (int i = 0; i < widthSegments; i++)
		{
			BReal x = max.x();
			BReal y = min.y() + dy * i;
			(*vertices)[count++] = BVector(x, y, -hh);
		}
		for (int i = 0; i < lengthSegments; i++)
		{
			BReal x = max.x() - dx * i;
			BReal y = max.y();
			(*vertices)[count++] = BVector(x, y, -hh);
		}
		for (int i = 0; i < widthSegments; i++)
		{
			BReal x = min.x();
			BReal y = max.y() - dy * i;
			(*vertices)[count++] = BVector(x, y, -hh);
		}

		for (int r = 1; r < heightSegments + 1; r++)
		{
			int first = columnCount * r;
			BReal z = dz * r;
			for (int c = 0; c < columnCount; c++)
			{
				(*vertices)[first + c] = (*vertices)[c] + BVector(0, 0, z);
			}
		}
	}

	{// make flank quads
		BIndexArray* flankIndices = new BIndexArray(columnCount * heightSegments * 4);
		BElement* flankPrimitive = new BElement(Primitive_Quads, flankIndices);
		for (int r = 0; r < heightSegments; r++)
		{
			int head = columnCount * r;
			int pos = columnCount * r * 4;
			for (int c = 0; c < columnCount; c++)
			{
				int index0 = head + c;
				int index1 = head + (c + 1) % columnCount;
				int index2 = index0 + columnCount;
				int index3 = index1 + columnCount;
				(*flankIndices)[pos + c * 4] = index0;
				(*flankIndices)[pos + c * 4 + 1] = index1;
				(*flankIndices)[pos + c * 4 + 2] = index3;
				(*flankIndices)[pos + c * 4 + 3] = index2;
			}
		}
		boss->addElement(flankPrimitive);
	}

	if (topNumVerts == 0)
	{
		// make top quads.
		BElement* topPrimitive = new BElement(Primitive_Quads, 4, 4);
		boss->addElement(topPrimitive);
		// make bottom quads.
		BIndexArray* bottomIndices = new BIndexArray(4);
		bottomIndices->at(0) = 3;
		bottomIndices->at(1) = 2;
		bottomIndices->at(2) = 1;
		bottomIndices->at(3) = 0;
		BElement* bottomPrimitive = new BElement(Primitive_Quads, bottomIndices);
		boss->addElement(bottomPrimitive);
	}
	else
	{
		{// make bottom and top vertices.
			int col_count = lengthSegments - 1;
			for (int i = 1; i < lengthSegments; i++)
			{
				BReal y = dy * i;
				int bottomHead = flankNumVerts + col_count * (i - 1);
				int topHead = bottomHead + bottomNumVerts;
				for (int c = 0; c < col_count; c++)
				{
					const BVector& v = (*vertices)[c + 1];
					(*vertices)[bottomHead + c] = v + BVector(0, y, 0);
					(*vertices)[topHead + c] = v + BVector(0, y, height);
				}
			}
		}

		{// make bottom quads.
			int col_count = lengthSegments - 1;
			int row_count = widthSegments - 1;
			BIndexArray* bottomIndices = new BIndexArray(lengthSegments * widthSegments * 4);
			BElement* bottomPrimitive = new BElement(Primitive_Quads, bottomIndices);
			int outerFirst = 0;
			int innerFirst = flankNumVerts;
			int quadCount = 0;
			for (int r = 0; r < row_count - 1; r++)
			{
				int head = flankNumVerts + r * col_count;
				for (int c = 0; c < col_count - 1; c++)
				{
					int index0 = head + c;
					int index1 = index0 + col_count;
					int index2 = index1 + 1;
					int index3 = index0 + 1;
					(*bottomIndices)[quadCount++] = index0;
					(*bottomIndices)[quadCount++] = index1;
					(*bottomIndices)[quadCount++] = index2;
					(*bottomIndices)[quadCount++] = index3;
				}
			}
			innerIndices.reset();
			for (int i = 0; i < col_count; i++)
				innerIndices.append(innerFirst + i);
			for (int i = 0; i < row_count; i++)
				innerIndices.append(innerFirst + (col_count - 1) + col_count * i);
			for (int i = 0; i < col_count; i++)
				innerIndices.append(innerFirst + (col_count * row_count - 1) - i);
			for (int i = 0; i < row_count; i++)
				innerIndices.append(innerFirst + col_count * (row_count - i - 1));
			if (columnCount > 4)
			{
				int outerIndex = 0;
				int innerPos = 0;
				(*bottomIndices)[quadCount++] = outerIndex;
				(*bottomIndices)[quadCount++] = outerIndex + columnCount - 1;
				(*bottomIndices)[quadCount++] = innerIndices[innerPos];
				(*bottomIndices)[quadCount++] = outerIndex + 1;
				for (int i = 0; i < col_count - 1; i++)
				{
					int index0 = outerIndex + 1 + i;
					int index1 = index0 + 1;
					int index2 = innerPos + i;
					int index3 = index2 + 1;
					(*bottomIndices)[quadCount++] = innerIndices[index2];
					(*bottomIndices)[quadCount++] = innerIndices[index3];
					(*bottomIndices)[quadCount++] = index1;
					(*bottomIndices)[quadCount++] = index0;
				}

				outerIndex += lengthSegments;
				innerPos += col_count;
				(*bottomIndices)[quadCount++] = innerIndices[innerPos];
				(*bottomIndices)[quadCount++] = outerIndex + 1;
				(*bottomIndices)[quadCount++] = outerIndex;
				(*bottomIndices)[quadCount++] = outerIndex - 1;
				for (int i = 0; i < row_count - 1; i++)
				{
					int index0 = outerIndex + 1 + i;
					int index1 = index0 + 1;
					int index2 = innerPos + i;
					int index3 = index2 + 1;
					(*bottomIndices)[quadCount++] = innerIndices[index2];
					(*bottomIndices)[quadCount++] = innerIndices[index3];
					(*bottomIndices)[quadCount++] = index1;
					(*bottomIndices)[quadCount++] = index0;
				}

				outerIndex += widthSegments;
				innerPos += row_count;
				(*bottomIndices)[quadCount++] = innerIndices[innerPos];
				(*bottomIndices)[quadCount++] = outerIndex + 1;
				(*bottomIndices)[quadCount++] = outerIndex;
				(*bottomIndices)[quadCount++] = outerIndex - 1;
				for (int i = 0; i < row_count - 1; i++)
				{
					int index0 = outerIndex + 1 + i;
					int index1 = index0 + 1;
					int index2 = innerPos + i;
					int index3 = index2 + 1;
					(*bottomIndices)[quadCount++] = innerIndices[index2];
					(*bottomIndices)[quadCount++] = innerIndices[index3];
					(*bottomIndices)[quadCount++] = index1;
					(*bottomIndices)[quadCount++] = index0;
				}

				outerIndex += lengthSegments;
				innerPos += col_count;
				(*bottomIndices)[quadCount++] = innerIndices[innerPos];
				(*bottomIndices)[quadCount++] = outerIndex + 1;
				(*bottomIndices)[quadCount++] = outerIndex;
				(*bottomIndices)[quadCount++] = outerIndex - 1;
				for (int i = 0; i < row_count - 1; i++)
				{
					int index0 = outerIndex + 1 + i;
					int index1 = index0 + 1;
					int index2 = innerPos + i;
					int index3 = index2 + 1;
					(*bottomIndices)[quadCount++] = innerIndices[index2];
					(*bottomIndices)[quadCount++] = innerIndices[index3];
					(*bottomIndices)[quadCount++] = index1;
					(*bottomIndices)[quadCount++] = index0;
				}
			}
			boss->addElement(bottomPrimitive);
		}

		{// make top quads.
			int col_count = lengthSegments - 1;
			int row_count = widthSegments - 1;
			BIndexArray* topIndices = new BIndexArray(lengthSegments * widthSegments * 4);
			BElement* topPrimitive = new BElement(Primitive_Quads, topIndices);
			int outerFirst = columnCount * heightSegments;
			int innerFirst = flankNumVerts + bottomNumVerts;
			int quadCount = 0;
			for (int r = 0; r < row_count - 1; r++)
			{
				int head = innerFirst + r * col_count;
				for (int c = 0; c < col_count - 1; c++)
				{
					int index0 = head + c;
					int index1 = index0 + 1;
					int index2 = index0 + col_count;
					int index3 = index1 + col_count;
					(*topIndices)[quadCount++] = index0;
					(*topIndices)[quadCount++] = index1;
					(*topIndices)[quadCount++] = index3;
					(*topIndices)[quadCount++] = index2;
				}
			}
			innerIndices.reset();
			for (int i = 0; i < col_count; i++)
				innerIndices.append(innerFirst + i);
			for (int i = 0; i < row_count; i++)
				innerIndices.append(innerFirst + (col_count - 1) + col_count * i);
			for (int i = 0; i < col_count; i++)
				innerIndices.append(innerFirst + (col_count * row_count - 1) - i);
			for (int i = 0; i < row_count; i++)
				innerIndices.append(innerFirst + col_count * (row_count - i - 1));
			if (columnCount > 4)
			{
				int outerIndex = outerFirst;
				int innerPos = 0;
				(*topIndices)[quadCount++] = outerIndex;
				(*topIndices)[quadCount++] = outerIndex + 1;
				(*topIndices)[quadCount++] = innerIndices[innerPos];
				(*topIndices)[quadCount++] = outerIndex + columnCount - 1;
				for (int i = 0; i < col_count - 1; i++)
				{
					int index0 = outerIndex + 1 + i;
					int index1 = index0 + 1;
					int index2 = innerPos + i;
					int index3 = index2 + 1;
					(*topIndices)[quadCount++] = index0;
					(*topIndices)[quadCount++] = index1;
					(*topIndices)[quadCount++] = innerIndices[index3];
					(*topIndices)[quadCount++] = innerIndices[index2];
				}

				outerIndex += lengthSegments;
				innerPos += col_count;
				(*topIndices)[quadCount++] = outerIndex - 1;
				(*topIndices)[quadCount++] = outerIndex;
				(*topIndices)[quadCount++] = outerIndex + 1;
				(*topIndices)[quadCount++] = innerIndices[innerPos];
				for (int i = 0; i < row_count - 1; i++)
				{
					int index0 = outerIndex + 1 + i;
					int index1 = index0 + 1;
					int index2 = innerPos + i;
					int index3 = index2 + 1;
					(*topIndices)[quadCount++] = index0;
					(*topIndices)[quadCount++] = index1;
					(*topIndices)[quadCount++] = innerIndices[index3];
					(*topIndices)[quadCount++] = innerIndices[index2];
				}

				outerIndex += widthSegments;
				innerPos += row_count;
				(*topIndices)[quadCount++] = outerIndex - 1;
				(*topIndices)[quadCount++] = outerIndex;
				(*topIndices)[quadCount++] = outerIndex + 1;
				(*topIndices)[quadCount++] = innerIndices[innerPos];
				for (int i = 0; i < row_count - 1; i++)
				{
					int index0 = outerIndex + 1 + i;
					int index1 = index0 + 1;
					int index2 = innerPos + i;
					int index3 = index2 + 1;
					(*topIndices)[quadCount++] = index0;
					(*topIndices)[quadCount++] = index1;
					(*topIndices)[quadCount++] = innerIndices[index3];
					(*topIndices)[quadCount++] = innerIndices[index2];
				}

				outerIndex += lengthSegments;
				innerPos += col_count;
				(*topIndices)[quadCount++] = outerIndex - 1;
				(*topIndices)[quadCount++] = outerIndex;
				(*topIndices)[quadCount++] = outerIndex + 1;
				(*topIndices)[quadCount++] = innerIndices[innerPos];
				for (int i = 0; i < row_count - 1; i++)
				{
					int index0 = outerIndex + 1 + i;
					int index1 = index0 + 1;
					int index2 = innerPos + i;
					int index3 = index2 + 1;
					(*topIndices)[quadCount++] = index0;
					(*topIndices)[quadCount++] = index1;
					(*topIndices)[quadCount++] = innerIndices[index3];
					(*topIndices)[quadCount++] = innerIndices[index2];
				}
			}
			boss->addElement(topPrimitive);
		}
	}
	boss->smooth();
}
